# 先用一个文件启动Flask服务
# -*- coding:utf-8 -*-

# 1.导入flask扩展
from flask import Flask, send_file
from flask import make_response
from flask import request
from flask import send_from_directory
from flask import g 
import pymysql
import json
import zipfile 
import random 
import shutil 
import os
import time

# 2.创建flask应用程序实例
# 需要传入__name__,作用是为了确定资源所在的路径
app = Flask(__name__)
# app.config['ENV'] = "development"
app.config['SECRET_KEY']="demo"

# 连接数据库
connect = pymysql.connect(
    host='localhost',
    user='root',
    passwd="",
    charset="utf8",
    autocommit=True,
    database="pdf_info"
)
cur = connect.cursor() # 创建游标，用于读取数据

# 3. 定义路由和视图函数
# Flask中定义路由是通过装饰器实现的
# 这是主页返回所有的数据
@app.route('/',methods=["GET","POST"])
def index():
    """主页返回所有文件列表"""
    try:
        query_info = "select * from info;"
        cur.execute(query_info)
        res = cur.fetchall()
    except Exception as e:
        info = {
            "data":[],
            "status":400,
            "info":"数据表获取失败:"+e
        }
        return json.dumps(info)
    else:
        info = {
            "data":[],
            "status":200,
            "info":"数据查找成功！"
        }
        for data in res: 
            dic = {
                't1': '','pro_name': '','code': '','num': '','date': '','year': '',
                'month': '','day': '','client_name': '','client_itin': '',
                'seller_name': '','seller_itin': '','car_num': '','car_type': '',
                'total_price': '','price': '','tax_rate': '','tax_price': '','dir': ""
            }
            item = list(data)
            for i,key in enumerate(dic.keys()):
                dic[key] = item[i]
            info['data'].append(dic)
        #设置响应头
        resp = make_response(json.dumps(info))
        resp.status = "200"            # 设置状态码
        resp.headers["Content-Type"] = "application/json"      # 设置响应头 
        resp.headers["Access-Control-Allow-Origin"] = "*"      # 设置响应头 
        return resp

@app.route('/query',methods=["GET","POST"])
def query():
    """根据键值对对数据进行查找 参数列表为：(key=字段, value=值)"""
    info = {
        "data":[],
        "status":200,
        "info":"数据查找成功！"
    }
    if request.method == 'POST':
        key = request.form.get("key","")
        value = request.form.get("value","")
        if key == "" or value == "":
            info["info"] = "数据为空"
            info["status"] = 400
            #设置响应头
            resp = make_response(json.dumps(info))
            resp.status = "400"            # 设置状态码
            resp.headers["Content-Type"] = "application/json"      # 设置响应头 
            resp.headers["Access-Control-Allow-Origin"] = "*"      # 设置响应头 
            return resp
        query_sql = "select * from info where {}='{}';".format(key,value)
        cur.execute(query_sql)
        res = cur.fetchall()
        for data in res:
            dic = {
                't1': '','pro_name': '','code': '','num': '','date': '','year': '',
                'month': '','day': '','client_name': '','client_itin': '',
                'seller_name': '','seller_itin': '','car_num': '','car_type': '',
                'total_price': '','price': '','tax_rate': '','tax_price': '','dir': ""
            }
            item = list(data)
            for i,key in enumerate(dic.keys()):
                dic[key] = item[i]
            info['data'].append(dic)
        #设置响应头
        resp = make_response(json.dumps(info))
        resp.status = "200"            # 设置状态码
        resp.headers["Content-Type"] = "application/json"      # 设置响应头
        resp.headers["Access-Control-Allow-Origin"] = "*"      # 设置响应头  
        return resp
    else:
        info["info"] = "查询失败"
        info["status"] = 400
        #设置响应头
        resp = make_response(json.dumps(info))
        resp.status = "400"            # 设置状态码
        resp.headers["Content-Type"] = "application/json"      # 设置响应头 
        resp.headers["Access-Control-Allow-Origin"] = "*"      # 设置响应头 
        return resp

@app.route('/download',methods=["GET","POST"])
def send():
    """批量下载文件"""
    info = {
        "data":[],
        "status":200,
        "info":"数据查找成功！"
    }
    if request.method == "POST":
        downloadlist = request.form.get("num","")
        if downloadlist !="":
            downloadlist = json.loads(downloadlist)
            # 批量文件打包发送和单文件发送
            if len(downloadlist) == 1:
                # single file
                query_sql = "select path,file from info where num={};".format(downloadlist[0])
                cur.execute(query_sql)
                res = cur.fetchall()[0]
                # response = make_response(send_from_directory(res[0],res[1],as_attachment=True))
                response = make_response(send_file(res[0]+res[1],as_attachment=True))
                # 如果 response.header 中没有添加  Access-Control-Expose-Headers 这个参数（代表：服务器允许浏览器访问的头（headers）的白名单），vue中就无法获取 content-disposition，即 res.headers['content-disposition'];无法找到
                response.headers["content-disposition"] = "attachment;filename=test.pdf"
                response.headers["FileName"] = "test.pdf"
                response.headers[" Access-Control-Expose-Headers"] = "FileName"
                response.headers["content-type"] = "application/pdf"
                response.headers["access-control-allow-origin"] = "*" 
                return response
            else:
                # multiple file https://www.cnblogs.com/hahaa/p/16512432.html
                query_sql = "select dir from info where num in{};".format(tuple(downloadlist))
                cur.execute(query_sql)
                res = cur.fetchall()
                times = str(int(time.time())+random.randint(0,100000))# 防止冲突，因为有可能有人同时下载文件
                des_path = "./temp/"+times+"/"
                if not os.path.exists("./temp/"):
                    os.mkdir("./temp/")
                mkdir_path = os.path.join(os.getcwd(),"temp",times)
                os.mkdir(mkdir_path)
                zip = zipfile.ZipFile(des_path+"/test.zip","w",zipfile.ZIP_DEFLATED)
                # 将指定文件复制到临时文件夹下
                for i,data in enumerate(res):
                    path = des_path + str(i) + ".pdf"
                    f = open(path,"wb")
                    src_file = open(data[0],"rb")
                    f.write(src_file.read())
                    f.close()
                    src_file.close()
                # 压缩批量文件
                for file in os.listdir(des_path):
                    if file.endswith('.pdf'):
                        zip.write(des_path+file) 
                zip.close()
                
                resp = make_response(send_from_directory(des_path,"test.zip",as_attachment=True))
                resp.headers["Content-Disposition"] = "attachment; filename=test.zip"
                resp.headers["Content-Type"] = "application/zip"
                resp.headers["Access-Control-Allow-Origin"] = "*"      # 设置响应头 
                
                g.dir = des_path
                # # 发送之后需要删除文件夹
                # @response.call_on_close
                # def on_close():
                #     shutil.rmtree(des_path)
                return resp
        else:
            info["info"] = "内容而为空"
            info["status"] = 400
            #设置响应头
            resp = make_response(json.dumps(info))
            resp.status = "400"            # 设置状态码
            resp.headers["Content-Type"] = "application/json"      # 设置响应头 
            resp.headers["Access-Control-Allow-Origin"] = "*"      # 设置响应头 
            return resp
    else:
        info["info"] = "下载失败"
        info["status"] = 400
        #设置响应头
        resp = make_response(json.dumps(info))
        resp.status = "400"            # 设置状态码
        resp.headers["Content-Type"] = "application/json"      # 设置响应头 
        resp.headers["Access-Control-Allow-Origin"] = "*"      # 设置响应头 
        return resp

# @app.after_request
# def on_close(res):
#     # PermissionError: [WinError 32] 另一个程序正在使用此文件，进程无法访问。
#     shutil.rmtree(g.dir)
#     return res

# 4. 启动服务
if __name__ == '__main__':
    app.run(port=5000)
    